#include "yaef_input.h"

#include <sstream>
#include <QWidget>
#include <QEvent>
#include <Windows.h>
#include <Xinput.h>

#include "keyboard.h"
#include "joystick.h"
#include "xboxcontroller.h"

/************************************************
 * ThreadTimer
 ************************************************/
ThreadTimer::ThreadTimer(QObject *parent):
  QObject(parent), _running(false)
{
}

void ThreadTimer::setInterval(int msecs)
{
  _interval = msecs;
}

int ThreadTimer::interval() const {
  return _interval;
}

void ThreadTimer::update()
{
  if (!_running)
    return;
  QDateTime cur = QDateTime::currentDateTime();
  if (_lastUpdate.msecsTo(cur) > _interval)
  {
    emit timeout();
    _lastUpdate = cur;
  }
}

void ThreadTimer::start()
{
  _lastUpdate = QDateTime::currentDateTime();
  _running = true;
}

void ThreadTimer::stop()
{
  _running = false;
}

/************************************************
 * InputDevice
 ************************************************/
InputDevice::InputDevice(QObject *parent)
  : ThreadTimer(parent), _currentKey(Ak_None)
{
  connect(this,SIGNAL(timeout()),this,SLOT(keyTimeout()));
}

void InputDevice::startKeyEmit()
{
  stopKeyEmit();
  emit key(_currentKey);
  setInterval(300);
  start();
}

void InputDevice::stopKeyEmit()
{
  stop();
}

void InputDevice::keyTimeout()
{
  if (interval()>50)
    setInterval(interval()-50);
  emit key(_currentKey);
}

/************************************************
 * InputThread
 ************************************************/
InputThread::InputThread(QObject *parent)
  : QThread(parent), _paused(false), _inputManager(NULL)
{
}

void InputThread::init(QWidget* w)
{
  init((HWND)(w->effectiveWinId()));
}

void InputThread::init(HWND hWnd)
{
  OIS::ParamList pl;

  std::ostringstream wnd;
  wnd << (unsigned int)hWnd;

  pl.insert(std::make_pair(std::string("WINDOW"), wnd.str()));

  _inputManager = OIS::InputManager::createInputSystem(pl);
  _inputManager->enableAddOnFactory(OIS::InputManager::AddOn_All);

  _devices << new Keyboard(this);
  _devices << new Joystick(this);
  _devices << new Joystick(this);
  _devices << new XBoxController(1,this);
  _devices << new XBoxController(2,this);

  foreach(InputDevice* d, _devices)
  {
    d->init(_inputManager);
    connect(d,SIGNAL(key(int)),this,SIGNAL(key(int)));
  }
}

void InputThread::run()
{
  while (true)
  {
    usleep(100);

    if (_paused)
      continue;

    foreach(InputDevice* d, _devices)
    {
      d->update();
    }

    MSG  msg;
    while(PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ))
    {
      TranslateMessage( &msg );
      DispatchMessage( &msg );
    }

    foreach(InputDevice* d, _devices)
    {
      d->capture();
    }
  }
}

/************************************************
 * NativeEventBlocker
 ************************************************/
NativeEventBlocker::NativeEventBlocker(QObject *parent)
  : QObject(parent)
{
}

bool NativeEventBlocker::eventFilter(QObject *, QEvent* e)
{
  return (e->type() == QEvent::KeyPress ||
          e->type() == QEvent::KeyRelease ||
          e->type() == QEvent::MouseButtonDblClick ||
          e->type() == QEvent::MouseButtonPress ||
          e->type() == QEvent::MouseButtonRelease ||
          e->type() == QEvent::MouseMove);
}

